<template>
  <div class="raceRank">
    <div class="r-body">
      <n-spin :show="showSpin" style="--n-opacity-spinning: 0">
        <el-table size="small" class="table" :data="rankList.records" :cell-style="cellStyle">
          <el-table-column prop="rank" label="排名" align="center" width="70px">
            <template #default="scoped">
              <div v-if="scoped.row.rank !== -1 && !scoped.row.award">
                {{ scoped.row.rank }}
              </div>
              <div v-if="scoped.row.rank === -1">*</div>
              <div v-if="scoped.row.award !== null && scoped.row.award">
                <el-tooltip class="box-item" effect="dark" :content="awardContent(scoped.row)" placement="top">
                  <div class="award" :style="{ background: awardColor(scoped.row) }">
                    <i class="iconfont icon-medal"> </i>
                    <div class="rank">
                      {{ scoped.row.rank }}
                    </div>
                  </div>
                </el-tooltip>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="displayId" label="用户" width="300px" align="center" class="isStar">
            <template #default="scoped">
              <div class="user">
                <div class="avatar">
                  <n-badge :offset="avatarOffset" value="Star" size="small" color="#ffc10a"
                    :show="scoped.row.rank === -1">
                    <el-avatar v-if="scoped.row.avatar === null || scoped.row.avatar === ''
                    ">{{ scoped.row.username[0] }}</el-avatar>
                    <n-avatar round size="large" :src="$getAvatarUrl(scoped.row.avatar)" v-else />
                  </n-badge>
                </div>
                <div>
                  <div class="id">
                    {{ scoped.row.username }}
                  </div>
                  <div>
                    {{ scoped.row.school }}
                  </div>
                </div>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="realName" label="真实姓名" align="center" v-if="rankName === 'realname'"></el-table-column>
          <el-table-column prop="nickname" label="昵称" align="center" v-if="rankName === 'nickname'"></el-table-column>
          <el-table-column prop="stageScore" label="阶段" align="center" width="900">
            <template #header>
              <div class="stage-header">
                <div v-for="(item, index) in tiantiStage.stage.length + 1" class="header-item">
                  {{ stageName(index) }}
                </div>
              </div>
            </template>
            <template #default="scoped">
              <div class="progress">
                <div class="progress-item" v-for="(item, index) in tiantiStage.stage.length + 1">
                  <n-progress type="line" :percentage="getProgress(index + 1, scoped.row.stageScore)" :height="18"
                    border-radius="12px 12px 12px 12px" :indicator-placement="'inside'" v-show="index === tiantiStage.stage.length &&
                      !isHaveStage(index + 1, scoped.row.effective)
                      " :color="getColor(index, scoped.row.effective)">
                    <template #default>
                      <div class="stage" v-show="index + 1 <= scoped.row.effective &&
                        getPosition(
                          index + 1,
                          scoped.row.stageScore,
                          scoped.row.effective
                        ) === 'inside'
                        ">
                        <div class="item" :style="{
                          'background-color': StageColor[index],
                        }">
                          {{ index + 1 }}
                        </div>
                      </div>
                    </template>
                  </n-progress>
                  <n-progress type="line" :percentage="getProgress(index + 1, scoped.row.stageScore)" :height="18"
                    :border-radius="'12px 12px 12px 12px'" :indicator-placement="'inside'" v-show="index !== 0 &&
                      index !== tiantiStage.stage.length &&
                      !isHaveStage(index + 1, scoped.row.effective)
                      " :color="getColor(index, scoped.row.effective)">
                    <template #default>
                      <div class="stage" v-show="index + 1 <= scoped.row.effective &&
                        getPosition(
                          index + 1,
                          scoped.row.stageScore,
                          scoped.row.effective
                        ) === 'inside'
                        ">
                        <div class="item" :style="{
                          'background-color': StageColor[index],
                        }">
                          {{ index + 1 }}
                        </div>
                      </div>
                    </template>
                  </n-progress>
                  <n-tooltip trigger="hover" style="background-color: #fff; color: #000" class="show">
                    <template #trigger>
                      <n-progress type="line" :percentage="getProgress(index + 1, scoped.row.stageScore)
                        " :height="18" :border-radius="'12px 12px 12px 12px'" :indicator-placement="getPosition(
          index + 1,
          scoped.row.stageScore,
          scoped.row.effective
        )
          " v-show="index !== 0 &&
          index !== tiantiStage.stage.length &&
          isHaveStage(index + 1, scoped.row.effective)
          " :processing="true" :color="progressColor[index]">
                        <template #default>
                          <div class="stage" v-show="index + 1 <= scoped.row.effective &&
                            getPosition(
                              index + 1,
                              scoped.row.stageScore,
                              scoped.row.effective
                            ) === 'inside'
                            ">
                            <div class="item" :style="{
                              'background-color': StageColor[index],
                            }">
                              {{ index + 1 }}
                            </div>
                          </div>
                          <div class="outSatge" v-show="index + 1 <= scoped.row.effective &&
                            getPosition(
                              index + 1,
                              scoped.row.stageScore,
                              scoped.row.effective
                            ) === 'outside'
                            ">
                            <div class="item" :style="{
                              'background-color': StageColor[index],
                            }">
                              {{ index + 1 }}
                            </div>
                          </div>
                        </template>
                      </n-progress>
                    </template>
                    <div class="title">
                      {{ stageName(index) }}
                      <div class="tab" v-show="isFirst(index + 1, scoped.row.vanguardScore)">
                        <i class="iconfont icon-xianfeng"></i>
                      </div>
                    </div>
                    <div class="totalScore">
                      总分:
                      {{
                        showTotalScore(
                          index + 1,
                          scoped.row.stageScore,
                      scoped.row.vanguardScore
                      )
                      }}
                    </div>
                    <div class="score" v-for="(pro, local) in proStage[index + 1]"
                      v-show="isShowPro(pro, scoped.row.submissionInfo)" @click="toStatus(scoped.row.submitIdInfo[pro])"
                      :class="{
                        zero:
                          scoped.row.statusInfo[pro] !== 0 ||
                          scoped.row.statusInfo[pro] !== 1,
                        part: scoped.row.statusInfo[pro] === 1,
                        full: scoped.row.statusInfo[pro] === 0,
                      }">
                      {{ showProTitle(pro) }} :&nbsp;
                      {{ scoped.row.submissionInfo[pro] }}分
                    </div>
                  </n-tooltip>
                  <n-tooltip trigger="hover" style="background-color: #fff; color: #000" class="show">
                    <template #trigger>
                      <n-progress type="line" :percentage="getProgress(index + 1, scoped.row.stageScore)
                        " :height="18" border-radius="12px 12px 12px 12px" :indicator-placement="getPosition(
          index + 1,
          scoped.row.stageScore,
          scoped.row.effective
        )
          " v-show="index === 0" :processing="true" :color="progressColor[index]">
                        <template #default>
                          <div class="stage" v-show="index + 1 <= scoped.row.effective &&
                            getPosition(
                              index + 1,
                              scoped.row.stageScore,
                              scoped.row.effective
                            ) === 'inside'
                            ">
                            <div class="item" :style="{
                              'background-color': StageColor[index],
                            }">
                              {{ index + 1 }}
                            </div>
                          </div>
                          <div class="outSatge" v-show="index + 1 <= scoped.row.effective &&
                            getPosition(
                              index + 1,
                              scoped.row.stageScore,
                              scoped.row.effective
                            ) === 'outside'
                            ">
                            <div class="item" :style="{
                              'background-color': StageColor[index],
                            }">
                              {{ index + 1 }}
                            </div>
                          </div>
                        </template>
                      </n-progress>
                    </template>
                    <div class="title">
                      {{ stageName(index) }}
                    </div>
                    <div class="totalScore">
                      总分:
                      {{
                        showTotalScore(
                          index + 1,
                          scoped.row.stageScore,
                      scoped.row.vanguardScore
                      )
                      }}
                    </div>
                    <div class="score" v-for="(pro, local) in proStage[index + 1]"
                      v-show="isShowPro(pro, scoped.row.submissionInfo)" @click="toStatus(scoped.row.submitIdInfo[pro])"
                      :class="{
                        zero:
                          scoped.row.statusInfo[pro] !== 0 ||
                          scoped.row.statusInfo[pro] !== 1,
                        part: scoped.row.statusInfo[pro] === 1,
                        full: scoped.row.statusInfo[pro] === 0,
                      }">
                      {{ showProTitle(pro) }}
                      :&nbsp; {{ scoped.row.submissionInfo[pro] }}分
                    </div>
                  </n-tooltip>
                  <n-tooltip trigger="hover" style="background-color: #fff; color: #000" class="show">
                    <template #trigger>
                      <n-progress type="line" :percentage="getProgress(index + 1, scoped.row.stageScore)
                        " :height="18" border-radius="12px 12px 12px 12px" :indicator-placement="'inside'" v-show="index === tiantiStage.stage.length &&
          isHaveStage(index + 1, scoped.row.effective)
          " :processing="true" :color="progressColor[index]">
                        <template #default>
                          <div class="stage" v-show="index + 1 <= scoped.row.effective &&
                            getPosition(
                              index + 1,
                              scoped.row.stageScore,
                              scoped.row.effective
                            ) === 'inside'
                            ">
                            <div class="item" :style="{
                              'background-color': StageColor[index],
                            }">
                              {{ index + 1 }}
                            </div>
                          </div>
                          <div class="outSatge" v-show="index + 1 <= scoped.row.effective &&
                            getPosition(
                              index + 1,
                              scoped.row.stageScore,
                              scoped.row.effective
                            ) === 'outside'
                            ">
                            <div class="item" :style="{
                              'background-color': StageColor[index],
                            }">
                              {{ index + 1 }}
                            </div>
                          </div>
                        </template>
                      </n-progress>
                    </template>
                    <div class="title">
                      {{ stageName(index) }}
                      <div class="tab" v-show="isFirst(index + 1, scoped.row.vanguardScore)">
                        <i class="iconfont icon-xianfeng"></i>
                      </div>
                    </div>
                    <div class="totalScore">
                      总分:
                      {{
                        showTotalScore(
                          index + 1,
                          scoped.row.stageScore,
                      scoped.row.vanguardScore
                      )
                      }}
                    </div>
                    <div class="score" v-for="(pro, local) in proStage[index + 1]"
                      v-show="isShowPro(pro, scoped.row.submissionInfo)" @click="toStatus(scoped.row.submitIdInfo[pro])"
                      :class="{
                        zero:
                          scoped.row.statusInfo[pro] !== 0 ||
                          scoped.row.statusInfo[pro] !== 1,
                        part: scoped.row.statusInfo[pro] === 1,
                        full: scoped.row.statusInfo[pro] === 0,
                      }">
                      {{ showProTitle(pro) }}
                      :&nbsp; {{ scoped.row.submissionInfo[pro] }}分
                    </div>
                  </n-tooltip>
                </div>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="totalScore" label="总分" align="center">
            <template #default="scoped">
              <div class="t-all">
                <div class="totalScore">
                  {{ scoped.row.totalScore }}
                </div>
              </div>
            </template>
          </el-table-column>
        </el-table>
      </n-spin>
    </div>
    <div class="r-foot">
      <el-pagination class="pagination" :page-sizes="[20, 50, 99]" background small layout="prev, pager, next,sizes"
        :page-count="Number(rankList.total)" v-model:current-page="rankParams.pageNum"
        v-model:page-size="rankParams.pageSize" />
    </div>
  </div>
</template>

<script setup>
import {
  onMounted,
  ref,
  defineProps,
  toRefs,
  defineExpose,
  watch,
  onUnmounted,
} from "vue";
import useStore from "@/store";
import { useRoute, useRouter } from "vue-router";
import {
  getRaceRankAPI,
  getRaceProblemAPI,
  getRaceProblemAcAPI,
  getRaceProblemScoreAPI,
} from "@/api/ojAPI/ojAPI.js";
import {
  getRaceRankAdminAPI
} from "@/api/adminAPI/adminAPI.js"
import { debounce } from "@/utils/global.js";
const props = defineProps({
  rankName: {
    type: String,
    default: "",
  },
  showStar: {
    type: Boolean,
    default: false,
  },
  showAuto: {
    type: Boolean,
    default: false,
  },
  rankParams: {
    type: Object,
    default: {
      pageSize: 20,
      pageNum: 1,
      searchValue: "",
    },
  },
  awardConfig: {
    type: Array,
    default: [],
  },
  location: {
    tyep: Boolean,
    default: false,
  },
  tiantiStage: {
    type: Object,
    default: {},
  },
  lockRank: {
    tyep: Boolean,
    default: true,
  }
});
const {
  rankName,
  showStar,
  showAuto,
  rankParams,
  awardConfig,
  location,
  tiantiStage,
  lockRank
} = toRefs(props);
onMounted(() => {
  getRaceRank();
  getRaceProblem();
});
const deboundTime = ref(null);
const route = useRoute();
const router = useRouter();
const rankList = ref({
  records: [],
  total: 0,
});
const progressColor = [
  "#daf7ff",
  "#eedfc3",
  "#ebacac",
  "rgb(71 177 159/ 72%)",
  "rgb(105,187,98/ 72%)",
  "rgb(179 187 32 / 74%)",
  "rgb(132 50 216/ 72%)",
  "rgb(163 32 80 / 72%)",
  "rgb(163 32 32 / 88%)",
  "rgb(134 29 177 / 74%)",
];
const StageColor = [
  "#cfe2e8",
  "#daceb9",
  "#e0b2b2",
  "rgb(71 177 159)",
  "rgb(105,187,98)",
  "rgb(179 187 32 )",
  "rgb(132 50 216)",
  "rgb(163 32 80 )",
  "rgb(163 32 32 )",
  "rgb(134 29 177 )",
];
const failColor = "rgb(182 182 182)";
const proStage = ref({});
const stage = ref({});
const problem = ref([]);
const avatarOffset = [-67, 20];
const problemScore = ref({});
const showSpin = ref(true);
const emit = defineEmits();
const toStatus = (data) => {
  if (location.value) {
    router.push(
      `/home/racePage/${route.params.rid}/evaluation/${data}`
    );
  }
};
const stageName = (index) => {
  return tiantiStage.value.names[index] ? tiantiStage.value.names[index] : `第${index + 1}阶段`
}
const cellStyle = (data) => {
  if (data.row.rank === -1) {
    return {
      background: "#ffffcc",
    };
  }
};
const getProgress = (index, stageItem) => {
  if (
    !stageItem[index] ||
    stageItem[index] === 0 ||
    stageItem[index] === undefined
  ) {
    return 0;
  } else if (stageItem[index] >= stage.value[index]) {
    return 100;
  } else {
    return parseInt((stageItem[index] / stage.value[index]) * 100);
  }
};
const getColor = (index, effective) => {
  if (index + 1 > effective) {
    return failColor;
  }
  return progressColor[index];
};
const awardContent = (row) => {
  let name = "";
  for (let i = 0; i < awardConfig.value.length; i++) {
    if (parseInt(awardConfig.value[i].level) === row.award) {
      name = awardConfig.value[i].name;
    }
  }
  return name;
};
const awardColor = (row) => {
  let color = "";
  for (let i = 0; i < awardConfig.value.length; i++) {
    if (parseInt(awardConfig.value[i].level) === row.award) {
      color = awardConfig.value[i].backColor;
    }
  }
  return color;
};
const isShowPro = (pro, info) => {
  if (info[pro] !== undefined) {
    return true;
  }
};
const isHaveStage = (index, stageItem) => {
  if (index <= stageItem) {
    return true;
  }
  return false;
};
const showProTitle = (pro) => {
  let title = "";
  problem.value.forEach((item) => {
    if (pro == item.pid) {
      title = item.displayTitle;
    }
  });
  return title;
};
const toProblem = (pro) => {
  let data = {};
  problem.value.forEach((item) => {
    if (item.pid == pro) {
      data = item;
    }
  });
  if (location.value) {
    router.push(
      `/home/racePage/${route.params.rid}/problem/${data.pid}?proId=${data.id}`
    );
  }
};
const isFirst = (index, vanguardScore) => {
  if (vanguardScore[index] !== undefined) {
    return true;
  }
  return false;
};
const isProcessing = (index, length) => {
  if (index === length) {
    return true;
  }
  return false;
};
const getPosition = (index, stageItem, effective) => {
  if (
    !stageItem[index] ||
    stageItem[index] === 0 ||
    stageItem[index] === undefined ||
    index > effective
  ) {
    return "inside";
  } else if (stageItem[index] >= stage.value[index]) {
    return "outside";
  } else {
    return "inside";
  }
};
const showTotalScore = (index, score, vanguardScore) => {
  if (vanguardScore[index] !== undefined) {
    return score[index] + vanguardScore[index];
  }
  if (score[index] === undefined) {
    return 0;
  }
  return score[index];
};
const getRaceRank = () => {
  if (deboundTime.value) {
    clearTimeout(deboundTime.value);
  }
  deboundTime.value = setTimeout(async () => {
    const removeStar = showStar.value ? 1 : 0;
    const data = {
      pageSize: rankParams.value.pageSize,
      pageNum: rankParams.value.pageNum,
      removeStar: removeStar,
      cid: route.params.rid,
      keyword: rankParams.value.searchValue,
    };
    if (lockRank.value) {
      await getRaceRankAPI(data).then((res) => {
        if (res.data.code === 200) {
          rankList.value = res.data.data;
          showSpin.value = false;
        }
      });
    } else {
      await getRaceRankAdminAPI(data).then((res) => {
        if (res.data.code === 200) {
          rankList.value = res.data.data;
          showSpin.value = false;
        }
      });
    }
  });
};
const getRaceProblem = debounce(async () => {
  await getRaceProblemAPI(route.params.rid)
    .then((res) => {
      if (res.data.code === 200) {
        problem.value = res.data.data;
        for (let i = 0; i <= tiantiStage.value.stage.length; i++) {
          proStage.value[i + 1] = [];
          stage.value[i + 1] = 0;
        }
        res.data.data.forEach((item) => {
          if (item.stage <= tiantiStage.value.stage.length + 1) {
            proStage.value[item.stage].push(item.pid);
          }
        });
        getRaceProblemScore();
      }
    })
    .catch((err) => {
      console.log(err);
    });
}, 100);
const getRaceProblemScore = debounce(async () => {
  let data = [];
  problem.value.forEach((item) => {
    data.push(item.pid);
  });
  await getRaceProblemScoreAPI(route.params.rid, data).then((res) => {
    if (res.data.code === 200) {
      problemScore.value = res.data.data;
      for (let i in stage.value) {
        proStage.value[i].forEach((item) => {
          stage.value[i] += Number(res.data.data[item]);
        });
      }
    }
  });
}, 100);
defineExpose({ getRaceRank, getRaceProblem });
</script>

<style lang="less" scoped>
.raceRank {
  width: 100%;

  .r-body {
    margin-top: 10px;

    .table {
      height: 65vh;

      .award {
        width: 35px;
        height: 35px;
        display: flex;
        margin-left: 6px;
        color: #fff;
        border-radius: 50%;
        display: flex;
        justify-content: center;
        align-items: center;

        .rank {
          font-size: 10px;
        }

        .iconfont {
          font-size: 13px;
        }
      }

      .user {
        display: flex;
        align-items: center;
        justify-content: left;

        .avatar {
          display: flex;
          align-items: center;
          margin-right: 10px;
          margin-left: 80px;
        }

        .id {
          display: flex;
          align-items: center;
        }
      }

      .progress {
        height: 40px;
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;

        .progress-item {
          width: 100%;
          display: flex;
          align-items: center;
          position: relative;
        }

      }

      .totalScore {
        font-size: 1.0645rem;
        font-weight: 550;
      }

      .stage {
        position: absolute;
        color: #fff;
        display: flex;
        align-items: center;
        justify-content: right;
        font-size: 1.0354rem;
        left: 2px;
        min-width: 18px;
        width: 100%;

        .item {
          width: 18px;
          height: 18px;
          border-radius: 50%;
          display: flex;
          justify-content: center;
          align-items: center;
          box-shadow: 1px 1px 2px #a9a7a7, inset -2px -3px 6px #757373;
        }
      }

      .outSatge {
        position: absolute;
        color: #fff;
        display: flex;
        align-items: center;
        justify-content: right;
        font-size: 1.0354rem;
        top: -4px;
        right: -4px;
        width: 100%;
        z-index: 100;

        .item {
          width: 28px;
          height: 28px;
          border-radius: 50%;
          display: flex;
          justify-content: center;
          align-items: center;
          box-shadow: inset 2px 2px 2px #918d8d8e, -1px -2px 5px #acaaaa;
        }
      }

      .stage-header {
        width: 100%;
        display: flex;
        align-items: center;

        .header-item {
          display: flex;
          flex: 1;
          justify-content: center;
        }
      }
    }

    .isStar {
      background-color: #ffffcc;
    }
  }

  .r-foot {
    margin: 0 auto;
    margin-top: 10px;
    display: flex;
    justify-content: center;
  }

  .detail {
    background-color: rgb(240, 244, 250);
    padding: 15px 0 30px 0;
    border-radius: 10px;

    .btn {
      width: 120px;
      margin: 10px 1%;
    }
  }
}

::v-deep(.el-table td:first-child) {
  border-left: 1px solid #e2ecfa;
  border-radius: 10px 0 0 10px;
  padding: 2px;
  background: #fff;
}

::v-deep(.el-table td:last-child) {
  border-right: 1px solid #e2ecfa;
  border-radius: 0 10px 10px 0;
  padding: 2px;
  background: #fff;
}

.title {
  font-size: 1.0765rem;
  display: flex;
  justify-content: center;
  align-items: center;
  font-weight: 550;
}

.zero {
  color: rgba(228, 31, 31, 0.83);
  font-weight: 550;
}

.part {
  color: #0c61c9a1;
}

.full {
  color: #18a058 !important;
}

.score {
  cursor: pointer;
}

.score:hover {
  text-decoration: underline;
}

.icon-xianfeng {
  color: #ce3e3eb9;
  font-size: 1.0765rem;
  margin-left: 3px;
}

::v-deep(.n-progress-graph-line-fill) {
  box-shadow: inset 4px 4px 10px #827c7c68, inset -4px -4px 10px #8e8a8a8a;
}
</style>
